# -*- coding: utf-8 -*-

from manage import *
import threading
import time
import rect


class FakeMoveObject(MoveObject):

    def __init__(self, xy, v):
        self.xy = xy
        self.v = v
        self.target = xy.copy()
        self.begin = xy
        # self.full = threading.Lock()
        # self.full.acquire()

    def GetPos(self):
        return self.xy
    
    def GetV(self):
        return self.v
    
    def SetTarget(self, pos):
        if pos is None:
            return
        if np.linalg.norm(self.xy - self.target) > 0.1:
            return
        if np.linalg.norm(pos - self.target) < 0.1:
            return
        if np.linalg.norm(pos - self.begin) < 0.2:
            return

        # vec1 = self.target - self.begin
        # vec2 = pos - self.target
        # vec1 /= np.linalg.norm(vec1) + 0.001
        # vec2 /= np.linalg.norm(vec2) + 0.001
        # dot = (vec1 * vec2).sum()
        # if np.abs(dot + 1) < 0.2:
        #     return
        self.begin = self.xy
        self.target = pos

        # self.full.release()
    
    def ThreadStart(self):
        t = threading.Thread(target=self.Thread)
        t.setDaemon(True)
        t.start()
        return t
    
    def Thread(self):
        while True:
            self.Walk()
    
    def Walk(self):
        # self.full.acquire()
        target = self.target
        if target is None:
            return
        vec = target - self.xy
        t = np.linalg.norm(vec) / self.v
        if t <= 0.0:
            return
        vec /= np.linalg.norm(vec)
        # seg = 10
        # for i in range(seg):
        #     time.sleep(t / seg)
        #     self.xy += vec * self.v * (t / seg)
        if not hasattr(self, "t1"):
            self.t1 = time.time()
        t2 = time.time()
        self.xy += vec * self.v * (t2 - self.t1)
        self.t1 = t2



class FakePurser(FakeMoveObject, Purser):
    
    def GetRMin(self):
        return single.RMIN
    
    def GetRMax(self):
        return single.RMAX
    
    def GetInPoints(self):
        p = np.zeros((1, 2))
        p[:] = self.xy
        return p
    
    def Thread(self):
        while True:
            manager = self.manager()
            manager.OnUpdateTarget(self)
            self.Walk()


class FakeEscaper(FakeMoveObject):

    def Thread(self):
        while True:
            self.RandomTarget()
            self.Walk()
    
    def Stop(self):
        self.isStop = True
    
    def NewTarget(self):
        if hasattr(self, "isStop"):
            if self.isStop:
                return
        if np.linalg.norm(self.xy - self.target) > 0.1:
            return
        # if not hasattr(self, "pos_lst"):
        #     self.pos_lst = []
        # if len(self.pos_lst) == 0:
        #     pos = self.NewAim()
        #     if pos is None:
        #         return
        #     self.pos_lst = single.GetPath(self.GetPos(), pos)
        #     self.pos_lst = self.pos_lst.tolist()
        # self.target = self.pos_lst.pop(0)
        pos = self.NewAim()
        if pos is None:
            return
        self.target, _ = rect.GetTarget(self.xy, pos)
        # self.full.release()
    
    def NewAim(self):
        if not hasattr(self, "aim"):
            self.aim = self.xy
        if np.linalg.norm(self.aim - self.xy) < 0.1:
            self.aim = single.RandomPos()
        return self.aim


class FakeClickEscaper(FakeEscaper):
    
    def NewAim(self):
        if not hasattr(self, "click_pos"):
            self.click_pos = None
        return self.click_pos
    
    def OnClick(self, x, y):
        self.click_pos = np.array([x, y])


def Test():
    import muti2
    manager = muti2.Manager2()
    p_n = 3
    v_ = 0.3
    pursers = [None] * p_n
    for i in range(p_n):
        xy = single.RandomPos()
        v = np.sin(np.pi / p_n) * v_
        p = FakePurser(xy, v)
        pursers[i] = p
    xy = single.RandomPos()
    # escaper = FakeEscaper(xy, v_)
    escaper = FakeClickEscaper(xy, v_)
    manager.SetPursers(pursers)
    manager.SetEscaper(escaper)
    # for i in range(p_n):
    #     pursers[i].ThreadStart()
    # escaper.ThreadStart()
    return manager

def Update(manager):
    p_n = len(manager.pursers)
    for i in range(p_n):
        manager.OnUpdateTarget(manager.pursers[i])
    manager.escaper.NewTarget()
    for i in range(p_n):
        manager.pursers[i].Walk()
    manager.escaper.Walk()